package com.infopatent.shldevtools.util;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import static java.lang.Thread.sleep;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.infopatent.shldevtools.tools.GetBigFileMD5Tools;
import com.infopatent.shldevtools.tools.MySimpleZipTools;
import java.io.IOException;
import org.apache.log4j.LogManager;

/**
 * <pre>该类可以用于使用<code>socket</code>连接来传输文件,并进行文件的md5校验,校验失败的文件将重新传输<br>
 * 同时支持在文件接收端选择性的进行文件解压操作,这由接收端方法参数决定<br>
 * 此外,该类的文件传输支持多线程,断点续传.
 *
 * 其中 若传输端 使用 sendFileClient , 那么 接收端 使用 receiveFileServer
 * 若传输端     使用 sendFileServer 那么 接收端 使用 receiveFileClient
 * @author shaohailong
 */
public class JcOaSyncUtil {

    private static final org.apache.log4j.Logger log = LogManager.getLogger(JcOaSyncUtil.class);
    private static final ArrayList<File> holdFiles = new ArrayList<File>();
    private static final int BUFFER = 1024;
    private ServerSocket ssocket;

    /**
     * 不带参数的构造方法,当需要建立Client端, 接收或传输文件时使用该方法获取该类的实例
     */
    public JcOaSyncUtil() {

    }

    /**
     * <pre> 带端口参数的构造方法,当需要建立Server端(或同时作为Server端和Client端) 接收或传输文件时使用该构造方法<br>
     * 获取该类的实例.</pre>
     *
     * @param port
     */
    public JcOaSyncUtil(int port) throws IOException {
        this.ssocket = bingToServerPort(port);
    }

    private ServerSocket bingToServerPort(int port) throws IOException {

        ssocket = new ServerSocket(port);
        log.info("服务启动!绑定端口号:" + ssocket.getLocalPort());

        return ssocket;
    }

    public static void addHoldFile(File f) {
        JcOaSyncUtil.holdFiles.add(f);
    }

    /**
     * 作为client端, 向固定IP的固定端口的Server端发送文件
     *
     * @param serverIp server端IP
     * @param serverPort server端监听的端口
     * @param sendFilePath 等待发送的文件路径
     * @return 传输成功返回true, 出现异常返回false
     */
    public boolean sendFileClient(final String serverIp, final int serverPort, final String sendFilePath) {

        new Thread() {

            File sendFile = new File(sendFilePath);
            Socket socket;
            DataInputStream dis;
            DataOutputStream dos;
            DataInputStream fis;

            @Override
            public void run() {
                while (true) {

                    //传输文件
                    try {
                        sleep(2000);
                        socket = new Socket(serverIp, serverPort);
                        log.info("建立socket连接...");

                        dis = new DataInputStream(socket.getInputStream());

                        dos = new DataOutputStream(socket.getOutputStream());

                        fis = new DataInputStream(new FileInputStream(sendFilePath));

                        dos.writeUTF("sendFile");

                        //发送文件名称
                        dos.writeUTF(sendFile.getName());
                        log.info("发送文件名称:" + sendFile.getName());
                        //发送文件大小
                        dos.writeLong(sendFile.length());
                        log.info("发送文件大小:" + sendFile.length());
                        //文件跳过尺寸
                        long skipSize = dis.readLong();

                        if (skipSize <= 0) {
                            log.info("文件不存在,新建文件...");
                        } else {
                            log.info("文件已存在,续传文件...");
                            fis.skip(skipSize);
                        }

                        byte[] buf = new byte[BUFFER];
                        //开始传输文件
                        log.info("文件传输开始...");
                        int read;
                        while ((read = fis.read(buf)) != -1) {
                            dos.write(buf, 0, read);
                        }
                        dos.flush();

                        log.info("文件传输完成...");

                    } catch (Exception ex) {
                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                        continue;
                    } finally {
                        try {

                            dis.close();
                            dos.close();
                            fis.close();
                            socket.close();
                        } catch (Exception ex) {
                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                            continue;
                        }
                    }

                    //验证文件MD5
                    String localFileMd5 = GetBigFileMD5Tools.getMD5(sendFile);
                    try {
                        sleep(2000);
                        socket = new Socket(serverIp, serverPort);

                        dis = new DataInputStream(socket.getInputStream());

                        dos = new DataOutputStream(socket.getOutputStream());

                        fis = new DataInputStream(new FileInputStream(sendFilePath));

                        dos.writeUTF("checkMd5");
                        //发送文件名称
                        dos.writeUTF(sendFile.getName());

                        String distanceFileMd5 = dis.readUTF();

                        if (localFileMd5 == null ? distanceFileMd5 == null : localFileMd5.equals(distanceFileMd5)) {
                            log.info("文件:" + sendFile.getName() + " MD5验证通过.. 开始解压/确认完成远程文件.");
                            dos.writeUTF("md5Right");

                            String fileSaveOrDecompressResult = dis.readUTF();

                            if ("decompressSuccess".equals(fileSaveOrDecompressResult)) {
                                log.info("文件解压完成");
                                break;
                            } else if ("saveSuccess".equals(fileSaveOrDecompressResult)) {
                                log.info("文件传输完成");
                                break;
                            }
                        } else {
                            log.info("文件:" + sendFile.getName() + " MD5验证失败.. 开始删除远程文件.");
                            dos.writeUTF("md5Wrong");

                            String deleteResult = dis.readUTF();

                            if ("deleteDone".equals(deleteResult)) {
                                log.info("文件删除完成. 重新传输");
                            }
                        }

                    } catch (Exception ex) {
                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        try {

                            dis.close();
                            dos.close();
                            fis.close();
                            socket.close();
                        } catch (Exception ex) {
                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                            continue;
                        }
                    }

                }

            }
        }.start();

        return false;

    }

    /**
     * 作为server端, 监听固定端口, 然后接收文件
     *
     * @param listenPort
     * @param fileRootPath 接收文件的根路径
     * @param whetherDecompress 是否需要解压缩
     * @param decompressFolder 若需要解压缩,解压路径
     * @return 传输成功返回true, 出现异常返回false
     */
    public static boolean receiveFileServer(final int listenPort, final String fileRootPath, final boolean whetherDecompress, final String decompressFolder) {
        new Thread() {

            ServerSocket ss;
            Socket socket;
            DataInputStream dis;
            DataOutputStream dos;
            DataOutputStream fos;

            @Override
            public void run() {
                boolean whileFlag = false;

                try {
                    ss = new ServerSocket(listenPort);
                    whileFlag = true;
                } catch (IOException ex) {
                    Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                }

                while (whileFlag) {
                    try {
                        sleep(2000);
                        socket = ss.accept();
                        log.info("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());
                        dis = new DataInputStream(socket.getInputStream());

                        dos = new DataOutputStream(socket.getOutputStream());

                        String actionFlag = dis.readUTF();

                        if ("sendFile".equals(actionFlag)) {

                            //获取文件名称
                            String fileName = dis.readUTF();
                            log.info("接收文件名称:" + fileName);
                            //获取文件大小
                            Long fileSize = dis.readLong();
                            log.info("接收文件大小:" + fileSize);

                            File receiveFile = new File(fileRootPath, fileName);

                            if (receiveFile.getParentFile() != null) {
                                if (!receiveFile.getParentFile().exists()) {
                                    receiveFile.getParentFile().mkdirs();
                                }
                            }

                            if (receiveFile.exists()) {
                                if (receiveFile.length() > fileSize) {
                                    receiveFile.delete();
                                    dos.writeLong(0);
                                    fos = new DataOutputStream(new FileOutputStream(receiveFile));
                                } else {
                                    dos.writeLong(receiveFile.length());
                                    fos = new DataOutputStream(new FileOutputStream(receiveFile, true));
                                }
                            } else {
                                dos.writeLong(0);
                                fos = new DataOutputStream(new FileOutputStream(receiveFile));
                            }

                            //开始接收文件
                            log.info("开始接收文件...");
                            byte[] buf = new byte[BUFFER];
                            int read;
                            long passedlen = 0 + receiveFile.length();
                            while ((read = dis.read(buf)) != -1) {
                                passedlen += read;
                                fos.write(buf, 0, read);
                                log.info("文件[" + fileName + "]已经接收: " + passedlen * 100L / fileSize + "%");
                            }
                            fos.flush();
                            log.info("文件接收完成...");

                        } else if ("checkMd5".equals(actionFlag)) {
                            String receiveFileName = dis.readUTF();
                            File receiveFile = new File(fileRootPath, receiveFileName);
                            String mD5 = GetBigFileMD5Tools.getMD5(receiveFile);
                            dos.writeUTF(mD5);

                            String md5CheckResult = dis.readUTF();

                            if ("md5Right".equals(md5CheckResult)) {
                                if (whetherDecompress) {

                                    boolean isDatabaseFlag = receiveFile.getPath().toLowerCase().contains("database");

                                    if (isDatabaseFlag) {
                                        Runtime.getRuntime().exec("net stop mssqlserver");
                                        Thread.sleep(10000);
                                        Runtime.getRuntime().exec("net stop mssqlserver");
                                        Thread.sleep(10000);
                                    }

                                    MySimpleZipTools.decompressFile(receiveFile.getPath(), decompressFolder);

                                    if (isDatabaseFlag) {
                                        Runtime.getRuntime().exec("net start mssqlserver");
                                        Thread.sleep(10000);
                                        Runtime.getRuntime().exec("net start mssqlserver");
                                        Thread.sleep(10000);
                                    }

                                    dos.writeUTF("decompressSuccess");
                                    synchronized (JcOaSyncUtil.holdFiles) {
                                        JcOaSyncUtil.holdFiles.add(receiveFile);
                                    }
                                } else {
                                    dos.writeUTF("saveSuccess");
                                    synchronized (JcOaSyncUtil.holdFiles) {
                                        JcOaSyncUtil.holdFiles.add(receiveFile);
                                    }
                                }

                                log.info("文件接收完成!...");

                            } else if ("md5Wrong".equals(md5CheckResult)) {
                                receiveFile.delete();
                                dos.writeUTF("deleteDone");

                                log.info("md5验证错误文件删除完成,文件重新传输..");

                            }

                        }

                    } catch (Exception ex) {
                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        try {

                            dis.close();
                            dos.close();
                            fos.close();
                            socket.close();

                        } catch (Exception ex) {
                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        }.start();

        return false;

    }

    /**
     * 作为server端, 监听固定端口, 然后接收文件
     *
     * @param fileRootPath 接收文件的根路径
     * @param whetherDecompress 是否需要解压缩
     * @param decompressFolder 若需要解压缩,解压路径
     * @param whetherSendToOtherServer
     * @param otherServerIp
     * @param otherServerPort
     * @return 传输成功返回true, 出现异常返回false
     */
    public boolean receiveFileServer(final String fileRootPath, final boolean whetherDecompress, final String decompressFolder, final boolean whetherSendToOtherServer, final String otherServerIp, final int otherServerPort) {
        new Thread() {

            Socket socket;
            DataInputStream dis;
            DataOutputStream dos;
            DataOutputStream fos;

            @Override
            public void run() {
                while (true) {
                    try {
                        sleep(2000);
                        socket = ssocket.accept();
                        log.info("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());
                        dis = new DataInputStream(socket.getInputStream());

                        dos = new DataOutputStream(socket.getOutputStream());

                        String actionFlag = dis.readUTF();

                        if ("sendFile".equals(actionFlag)) {

                            //获取文件名称
                            String fileName = dis.readUTF();
                            log.info("接收文件名称:" + fileName);
                            //获取文件大小
                            Long fileSize = dis.readLong();
                            log.info("接收文件大小:" + fileSize);

                            File receiveFile = new File(fileRootPath, fileName);

                            if (receiveFile.getParentFile() != null) {
                                if (!receiveFile.getParentFile().exists()) {
                                    receiveFile.getParentFile().mkdirs();
                                }
                            }

                            if (receiveFile.exists()) {
                                if (receiveFile.length() > fileSize) {
                                    receiveFile.delete();
                                    dos.writeLong(0);
                                    fos = new DataOutputStream(new FileOutputStream(receiveFile));
                                } else {
                                    dos.writeLong(receiveFile.length());
                                    fos = new DataOutputStream(new FileOutputStream(receiveFile, true));
                                }
                            } else {
                                dos.writeLong(0);
                                fos = new DataOutputStream(new FileOutputStream(receiveFile));
                            }

                            //开始接收文件
                            log.info("开始接收文件...");
                            byte[] buf = new byte[BUFFER];
                            int read;
                            long passedlen = 0 + receiveFile.length();
                            while ((read = dis.read(buf)) != -1) {
                                passedlen += read;
                                fos.write(buf, 0, read);
                                log.info("文件[" + fileName + "]已经接收: " + passedlen * 100L / fileSize + "%");
                            }
                            fos.flush();
                            log.info("文件接收完成...");

                        } else if ("checkMd5".equals(actionFlag)) {
                            String receiveFileName = dis.readUTF();
                            File receiveFile = new File(fileRootPath, receiveFileName);
                            String mD5 = GetBigFileMD5Tools.getMD5(receiveFile);
                            dos.writeUTF(mD5);

                            String md5CheckResult = dis.readUTF();

                            if ("md5Right".equals(md5CheckResult)) {
                                if (whetherDecompress) {

                                    boolean isDatabaseFlag = receiveFile.getPath().toLowerCase().contains("database");

                                    if (isDatabaseFlag) {
                                        Runtime.getRuntime().exec("net stop mssqlserver");
                                        Thread.sleep(10000);
                                        Runtime.getRuntime().exec("net stop mssqlserver");
                                        Thread.sleep(10000);
                                    }

                                    MySimpleZipTools.decompressFile(receiveFile.getPath(), decompressFolder);

                                    if (isDatabaseFlag) {
                                        Runtime.getRuntime().exec("net start mssqlserver");
                                        Thread.sleep(10000);
                                        Runtime.getRuntime().exec("net start mssqlserver");
                                        Thread.sleep(10000);
                                    }

                                    dos.writeUTF("decompressSuccess");
                                    synchronized (JcOaSyncUtil.holdFiles) {
                                        JcOaSyncUtil.holdFiles.add(receiveFile);
                                    }
                                } else {
                                    dos.writeUTF("saveSuccess");
                                    synchronized (JcOaSyncUtil.holdFiles) {
                                        JcOaSyncUtil.holdFiles.add(receiveFile);
                                    }
                                }

                                if (whetherSendToOtherServer) {
                                    sendFileClient(otherServerIp, otherServerPort, receiveFile.getPath());
                                }

                                log.info("文件接收完成!...");

                            } else if ("md5Wrong".equals(md5CheckResult)) {
                                receiveFile.delete();
                                dos.writeUTF("deleteDone");

                                log.info("md5验证错误文件删除完成,文件重新传输..");

                            }

                        }

                    } catch (Exception ex) {
                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        try {

                            dis.close();
                            dos.close();
                            fos.close();
                            socket.close();

                        } catch (Exception ex) {
                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        }.start();
        return false;
    }

    /**
     * 作为server端, 监听固定端口等待请求, 然后将文件传输出去
     *
     * @param listenPort
     * @return 传输成功返回true, 出现异常返回false
     */
    public static boolean sendFileServer(final int listenPort) {
        new Thread() {

            ServerSocket ss;
            DataInputStream dis;
            DataOutputStream dos;
            DataInputStream fis;

            @Override
            public void run() {
                boolean whileFlag = false;

                try {
                    ss = new ServerSocket(listenPort);
                    whileFlag = true;
                } catch (IOException ex) {
                    Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                }

                while (whileFlag) {

                    log.info("进入工作循环 -- sendFileServer");

                    try {
                        final Socket socket = ss.accept();

                        new Thread() {
                            @Override
                            public void run() {
                                if (JcOaSyncUtil.holdFiles.size() > 0) {

                                    File sendFile = JcOaSyncUtil.holdFiles.get(0);
                                    synchronized (JcOaSyncUtil.holdFiles) {
                                        JcOaSyncUtil.holdFiles.remove(sendFile);
                                    }

                                    //传输文件
                                    try {

                                        log.info("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());

                                        dis = new DataInputStream(socket.getInputStream());

                                        dos = new DataOutputStream(socket.getOutputStream());

                                        fis = new DataInputStream(new FileInputStream(sendFile));

                                        dos.writeUTF("sendFile");

                                        //发送文件名称
                                        dos.writeUTF(sendFile.getName());
                                        log.info("发送文件名称:" + sendFile.getName());
                                        //发送文件大小
                                        dos.writeLong(sendFile.length());
                                        log.info("发送文件大小:" + sendFile.length());
                                        //文件跳过尺寸
                                        long skipSize = dis.readLong();

                                        if (skipSize <= 0) {
                                            log.info("文件不存在,新建文件...");
                                        } else {
                                            log.info("文件已存在,续传文件...");
                                            fis.skip(skipSize);
                                        }

                                        byte[] buf = new byte[BUFFER];
                                        //开始传输文件
                                        log.info("文件传输开始...");
                                        int read;
                                        while ((read = fis.read(buf)) != -1) {
                                            dos.write(buf, 0, read);
                                        }
                                        dos.flush();

                                        log.info("文件传输完成...");

                                    } catch (Exception ex) {
                                        synchronized (JcOaSyncUtil.holdFiles) {
                                            JcOaSyncUtil.holdFiles.add(sendFile);
                                        }
                                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                                    } finally {
                                        try {
                                            dis.close();
                                            dos.close();
                                            fis.close();
                                            socket.close();

                                        } catch (Exception ex) {
                                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                                        }
                                    }

                                    //验证文件MD5
                                    String localFileMd5 = GetBigFileMD5Tools.getMD5(sendFile);
                                    try {
                                        Socket socket = ss.accept();
                                        log.info("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());
                                        dis = new DataInputStream(socket.getInputStream());

                                        dos = new DataOutputStream(socket.getOutputStream());

                                        fis = new DataInputStream(new FileInputStream(sendFile));

                                        dos.writeUTF("checkMd5");
                                        //发送文件名称
                                        dos.writeUTF(sendFile.getName());

                                        String distanceFileMd5 = dis.readUTF();

                                        if (localFileMd5 == null ? distanceFileMd5 == null : localFileMd5.equals(distanceFileMd5)) {
                                            log.info("文件:" + sendFile.getName() + " MD5验证通过.. 开始解压/确认完成远程文件.");
                                            dos.writeUTF("md5Right");

                                            String fileSaveOrDecompressResult = dis.readUTF();

                                            if ("decompressSuccess".equals(fileSaveOrDecompressResult)) {
                                                log.info("文件解压完成");
                                                synchronized (JcOaSyncUtil.holdFiles) {
                                                    JcOaSyncUtil.holdFiles.remove(sendFile);
                                                }
                                            } else if ("saveSuccess".equals(fileSaveOrDecompressResult)) {
                                                log.info("文件传输完成");
                                                synchronized (JcOaSyncUtil.holdFiles) {
                                                    JcOaSyncUtil.holdFiles.remove(sendFile);
                                                }
                                            }
                                        } else {
                                            log.info("文件:" + sendFile.getName() + " MD5验证失败.. 开始删除远程文件.");
                                            dos.writeUTF("md5Wrong");

                                            String deleteResult = dis.readUTF();

                                            if ("deleteDone".equals(deleteResult)) {
                                                log.info("文件删除完成. 重新传输");
                                            }

                                            synchronized (JcOaSyncUtil.holdFiles) {
                                                JcOaSyncUtil.holdFiles.add(sendFile);
                                            }

                                        }

                                    } catch (Exception ex) {
                                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                                        synchronized (JcOaSyncUtil.holdFiles) {
                                            JcOaSyncUtil.holdFiles.add(sendFile);
                                        }
                                    } finally {
                                        try {

                                            dis.close();
                                            dos.close();
                                            fis.close();
                                            socket.close();

                                        } catch (Exception ex) {
                                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                                        }
                                    }
                                } else {

                                    //传输文件
                                    try {

                                        log.info("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());

                                        dis = new DataInputStream(socket.getInputStream());

                                        dos = new DataOutputStream(socket.getOutputStream());

                                        dos.writeUTF("noFile");

                                        dos.flush();

                                        log.info("无文件进行传输");

                                    } catch (Exception ex) {
                                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                                    } finally {
                                        try {
                                            dis.close();
                                            dos.close();
                                            if (fis != null) {
                                                fis.close();
                                            }

                                            socket.close();

                                        } catch (Exception ex) {
                                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                                        }
                                    }

                                    try {
                                        log.info("目前待传送列表为空, 1秒后重新检测");
                                        sleep(2000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }.start();
                    } catch (IOException ex) {
                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                    }

                }

            }
        }.start();
        return false;
    }

    /**
     * 作为client端, 向固定IP的server端请求文件
     *
     * @param serverIp server端IP
     * @param serverPort server端监听的端口
     * @param fileRootPath 接收文件的根路径
     * @param whetherDecompress 是否解压
     * @param decompressFolder 解压路径
     * @return 传输成功返回true, 出现异常返回false
     */
    public static boolean receiveFileClient(final String serverIp, final int serverPort, final String fileRootPath, final boolean whetherDecompress, final String decompressFolder) {

        new Thread() {
            Socket socket;
            DataInputStream dis;
            DataOutputStream dos;
            DataOutputStream fos;

            @Override
            public void run() {
                while (true) {

                    log.info("进入工作循环 -- receiveFileClient");

                    try {

                        socket = new Socket(serverIp, serverPort);

                        dis = new DataInputStream(socket.getInputStream());

                        dos = new DataOutputStream(socket.getOutputStream());

                        String actionFlag = dis.readUTF();

                        if ("sendFile".equals(actionFlag)) {

                            //获取文件名称
                            String fileName = dis.readUTF();
                            log.info("接收文件名称:" + fileName);
                            //获取文件大小
                            Long fileSize = dis.readLong();
                            log.info("接收文件大小:" + fileSize);

                            File receiveFile = new File(fileRootPath, fileName);

                            if (receiveFile.getParentFile() != null) {
                                if (!receiveFile.getParentFile().exists()) {
                                    receiveFile.getParentFile().mkdirs();
                                }
                            }

                            if (receiveFile.exists()) {
                                if (receiveFile.length() > fileSize) {
                                    receiveFile.delete();
                                    dos.writeLong(0);
                                    fos = new DataOutputStream(new FileOutputStream(receiveFile));
                                } else {
                                    dos.writeLong(receiveFile.length());
                                    fos = new DataOutputStream(new FileOutputStream(receiveFile, true));
                                }
                            } else {
                                dos.writeLong(0);
                                fos = new DataOutputStream(new FileOutputStream(receiveFile));
                            }

                            //开始接收文件
                            log.info("开始接收文件...");
                            byte[] buf = new byte[BUFFER];
                            int read;
                            long passedlen = 0 + receiveFile.length();

                            while ((read = dis.read(buf)) != -1) {
                                passedlen += read;
                                fos.write(buf, 0, read);

                                if ((passedlen / BUFFER) % 1024 == 0) {
                                    log.info("文件[" + fileName + "]已经接收: " + passedlen * 100L / fileSize + "%");
                                }

                            }
                            fos.flush();
                            log.info("文件接收完成...");

                        } else if ("checkMd5".equals(actionFlag)) {
                            String receiveFileName = dis.readUTF();
                            File receiveFile = new File(fileRootPath, receiveFileName);
                            String mD5 = GetBigFileMD5Tools.getMD5(receiveFile);
                            dos.writeUTF(mD5);

                            String md5CheckResult = dis.readUTF();

                            if ("md5Right".equals(md5CheckResult)) {
                                if (whetherDecompress) {

                                    boolean isDatabaseFlag = receiveFile.getPath().toLowerCase().contains("database");

                                    if (isDatabaseFlag) {
                                        Runtime.getRuntime().exec("net stop mssqlserver");
                                        Thread.sleep(10000);
                                        Runtime.getRuntime().exec("net stop mssqlserver");
                                        Thread.sleep(10000);
                                    }

                                    MySimpleZipTools.decompressFile(receiveFile.getPath(), decompressFolder);

                                    if (isDatabaseFlag) {
                                        Runtime.getRuntime().exec("net start mssqlserver");
                                        Thread.sleep(10000);
                                        Runtime.getRuntime().exec("net start mssqlserver");
                                        Thread.sleep(10000);
                                    }

                                    dos.writeUTF("decompressSuccess");
                                } else {
                                    dos.writeUTF("saveSuccess");
                                }

                                log.info("文件接收完成!...");

                            } else if ("md5Wrong".equals(md5CheckResult)) {
                                receiveFile.delete();
                                dos.writeUTF("deleteDone");

                                log.info("md5验证错误文件删除完成,文件重新传输..");

                            }

                        } else if ("noFile".equals(actionFlag)) {
                            log.info("Server 端现在并无文件需要传送. 10秒后重试");
                            sleep(10000);
                        }

                    } catch (Exception ex) {
                        Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                        try {
                            sleep(1000);
                        } catch (InterruptedException ex1) {
                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex1);
                        }
                    } finally {
                        try {

                            if (dis != null) {
                                dis.close();
                            }
                            if (dos != null) {
                                dos.close();
                            }

                            if (fos != null) {
                                fos.close();
                            }
                            if (socket != null) {
                                socket.close();
                            }

                        } catch (Exception ex) {
                            Logger.getLogger(JcOaSyncUtil.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        }.start();

        return false;

    }

    public void testThread() {
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println(JcOaSyncUtil.holdFiles.size());
                    try {
                        sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    public static void main(String[] args) {
//        JcOaSyncUtil syncUtil = new JcOaSyncUtil();
//        syncUtil.testThread();
//        try {
//            sleep(4000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        syncUtil.holdFiles.add(new File(""));
//
//        try {
//            sleep(4000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        syncUtil.holdFiles.add(new File(""));
//
//        try {
//            sleep(4000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        syncUtil.holdFiles.add(new File(""));
//
//        try {
//            sleep(4000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        syncUtil.holdFiles.add(new File(""));

    }
}
